﻿using PoliticalClassifier.Calculations;
using PoliticalClassifier.DataSource;
using PoliticalClassifier.Support;
using System;
using System.Drawing;

namespace PoliticalClassifier.Application
{
    /// <summary>
    /// PoliticalClassifierModeler provides the primary API for clients of the 
    /// political classifier model to compute voter and candidate data, as well 
    /// as generate plots of results.
    /// </summary>
	public class PoliticalClassifierModeler
	{
		#region Construction
        /// <summary>
        /// Construct a new PoliticalClassifierModeler.
        /// </summary>
		public PoliticalClassifierModeler()
		{
			m_candidateManager = new PoliticalClassifier.Framework.CandidateManager();
			m_weightManager = new PoliticalClassifier.Framework.WeightManager();
		}
		#endregion

		#region Public Methods
        /// <summary>
        /// Load the data file specified in the FileName property.
        /// </summary>
        /// <returns>The results and any errors or warning encountered during data loading.</returns>
		public IDataSourceLoadResults Load()
		{
			try
			{
				return LastLoadResults = DataSetSource.Load(FileName);
			}
			catch (Exception)
			{
				return LastLoadResults = DataSetSource.CreateUnknownErrorLoadResults();
			}
		}

        /// <summary>
        /// Compute the results of the simulation.
        /// </summary>
        /// <returns>The results of the simulation.</returns>
		public ISimulationResults Compute()
		{
			m_PoliticalClassifierCalculate = new PoliticalClassifierCalculate(DataSetSource.VotersRecord, WeightManager, CandidateManager);
			return LastSimulationResults = m_PoliticalClassifierCalculate.Compute();
		}

        /// <summary>
        /// Generate an image of the plotted results.
        /// </summary>
        /// <param name="simulationResults">The simulation results.</param>
        /// <returns>The image of the plot.</returns>
		public Image PlotGraph(ISimulationResults simulationResults)
		{
			Range2D plotRange = new Range2D(-1.0, 1.0, -1.0, 1.0);
			double radiusOfPointCircle = 0.025;
			Image image = new PoliticalClassifier.PlotGenerator.PlotGenerator().CreatePlotImage(simulationResults.OverallVoterMedianPoint, m_PoliticalClassifierCalculate.TransformedPoints, plotRange, radiusOfPointCircle);
			return image;
		}
		#endregion

		#region Public Properties
        /// <summary>
        /// Gets the candidate manager, which contains data about the candidates/parties.
        /// </summary>
		public ICandidateManager CandidateManager
		{
			get { return m_candidateManager; }
		}
        
        /// <summary>
        /// Gets the weight manager, which contains data about the weights used in the calculation model.
        /// </summary>
		public IWeightManager WeightManager
		{
			get { return m_weightManager; }
		}

        /// <summary>
        /// Gets and sets the file path for the voter data file to use during the simulation.
        /// </summary>
		public String FileName
		{
			get { return m_fileName; }
			set { m_fileName = value; }
		}

        /// <summary>
        /// Gets the names of the columns in the voter data file.
        /// </summary>
		public string[] ColumnNames
		{
			get
			{
				if (DataSetSource != null)
					return DataSetSource.ColumnNames;
				return null;
			}
		}

        /// <summary>
        /// Gets the simulation results from the last performed simulation.
        /// </summary>
		public ISimulationResults LastSimulationResults { get; private set; }

        /// <summary>
        /// Gets the load results from the loading of the last voter data file.
        /// </summary>
		public IDataSourceLoadResults LastLoadResults { get; private set; }
		#endregion

		#region Private Properties
        /// <summary>
        /// Gets the data set source.
        /// </summary>
		IDataSetSource DataSetSource
		{
			get { return m_dataSetSource; }
		}
		#endregion

		#region Private Fields
		private IDataSetSource m_dataSetSource = new DataSetSource();
		private ICandidateManager m_candidateManager;
		private IWeightManager m_weightManager;
		private String m_fileName;
		private PoliticalClassifierCalculate m_PoliticalClassifierCalculate;
		#endregion
	}
}
